export class SocketClient {
    private ws: WebSocket | null = null;
    private url: string;
    private reconnectInterval: number;
    private maxReconnectAttempts: number;
    private reconnectAttempts: number = 0;
    private isManualDisconnect: boolean = false;

    // 事件回调函数
    onOpen?: (event: Event) => void;
    onMessage?: (data: string | ArrayBuffer) => void;
    onError?: (event: Event) => void;
    onClose?: (event: CloseEvent) => void;
    onReconnectAttempt?: (attempt: number) => void;
    onMaxReconnectAttemptsReached?: () => void;

    /**
     * 创建WebSocket客户端实例
     * @param url WebSocket服务器地址
     * @param reconnectInterval 重连间隔时间(毫秒)，默认3000ms
     * @param maxReconnectAttempts 最大重连次数，默认5次
     */
    constructor(
        url: string,
        reconnectInterval: number = 3000,
        maxReconnectAttempts: number = 5
    ) {
        this.url = url;
        this.reconnectInterval = reconnectInterval;
        this.maxReconnectAttempts = maxReconnectAttempts;
    }

    /**
     * 连接到WebSocket服务器
     */
    connect(): void {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
            console.warn('WebSocket已经处于连接状态');
            return;
        }

        try {
            this.ws = new WebSocket(this.url);
            this.isManualDisconnect = false;
            this.reconnectAttempts = 0;

            this.ws.onopen = (event) => {
                // console.log('WebSocket连接已建立');
                if (this.onOpen) {
                    this.onOpen(event);
                }
            };

            this.ws.onmessage = (event) => {
                if (this.onMessage) {
                    this.onMessage(event.data);
                }
            };

            this.ws.onerror = (event) => {
                console.error('WebSocket错误发生');
                if (this.onError) {
                    this.onError(event);
                }
            };

            this.ws.onclose = (event) => {
                console.log(`WebSocket连接已关闭，代码: ${event.code}, 原因: ${event.reason}`);
                if (this.onClose) {
                    this.onClose(event);
                }

                // 如果不是手动断开连接，并且未达到最大重连次数，则尝试重连
                if (!this.isManualDisconnect && this.reconnectAttempts < this.maxReconnectAttempts) {
                    this.reconnect();
                }
            };
        } catch (error) {
            console.error('WebSocket连接失败:', error);
            if (this.onError) {
                this.onError(new Event('connection_failed'));
            }
            this.reconnect();
        }
    }

    /**
     * 断开与WebSocket服务器的连接
     * @param code 关闭代码，默认1000(正常关闭)
     * @param reason 关闭原因
     */
    disconnect(code: number = 1000, reason: string = '手动断开连接'): void {
        if (this.ws) {
            this.isManualDisconnect = true;
            this.ws.close(code, reason);
            this.ws = null;
        }
    }

    /**
     * 发送消息到服务器
     * @param data 要发送的数据，可以是字符串、ArrayBuffer或Blob
     * @returns 是否发送成功
     */
    send(data: string | ArrayBuffer | Blob): boolean {
        if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
            console.error('WebSocket未连接，无法发送消息');
            return false;
        }

        try {
            this.ws.send(data);
            return true;
        } catch (error) {
            console.error('发送消息失败:', error);
            return false;
        }
    }

    /**
     * 发送JSON格式的消息
     * @param data 要发送的JSON数据
     * @returns 是否发送成功
     */
    sendJson(data: any): boolean {
        try {
            const jsonString = JSON.stringify(data);
            return this.send(jsonString);
        } catch (error) {
            console.error('JSON序列化失败:', error);
            return false;
        }
    }

    /**
     * 获取当前连接状态
     * @returns 连接状态
     */
    getReadyState(): number | null {
        return this.ws ? this.ws.readyState : null;
    }

    /**
     * 检查是否处于连接状态
     * @returns 是否连接
     */
    isConnected(): boolean {
        return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
    }

    /**
     * 尝试重新连接
     */
    private reconnect(): void {
        this.reconnectAttempts++;

        if (this.reconnectAttempts > this.maxReconnectAttempts) {
            console.error(`已达到最大重连次数(${this.maxReconnectAttempts})，停止重连`);
            if (this.onMaxReconnectAttemptsReached) {
                this.onMaxReconnectAttemptsReached();
            }
            return;
        }

        console.log(`第${this.reconnectAttempts}次尝试重连，将在${this.reconnectInterval}ms后进行`);
        if (this.onReconnectAttempt) {
            this.onReconnectAttempt(this.reconnectAttempts);
        }

        setTimeout(() => {
            this.connect();
        }, this.reconnectInterval);
    }
}
